package org.jeecg.modules.friends.auth.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.common.exception.MakeFriendsBaseException;
import org.jeecg.common.util.RealNameAuthenticationUtils;
import org.jeecg.modules.friends.auth.dto.AuthDetailInfo;
import org.jeecg.modules.friends.auth.dto.AuthInfo;
import org.jeecg.modules.friends.auth.dto.EducationAuthInfo;
import org.jeecg.modules.friends.auth.dto.IDCardAuthInfo;
import org.jeecg.modules.friends.auth.dto.JobAuthInfo;
import org.jeecg.modules.friends.auth.dto.UserExtDTO;
import org.jeecg.modules.friends.auth.entity.UserAuthentication;
import org.jeecg.modules.friends.auth.mapper.UserAuthenticationMapper;
import org.jeecg.modules.friends.auth.param.EditAuthInfoRequest;
import org.jeecg.modules.friends.auth.service.IUserAuthenticationService;
import org.jeecg.modules.friends.dao.InvitedUserDAO;
import org.jeecg.modules.friends.dao.SystemConfigDAO;
import org.jeecg.modules.friends.enums.AuthStatusEnum;
import org.jeecg.modules.friends.enums.AuthTypeEnum;
import org.jeecg.modules.friends.enums.EducationTypeEnum;
import org.jeecg.modules.friends.model.InvitedUserDO;
import org.jeecg.modules.friends.model.SystemConfigDO;
import org.jeecg.modules.friends.service.VipUserService;
import org.jeecg.modules.friends.user.entity.User;
import org.jeecg.modules.friends.user.mapper.UserMapper;
import org.jeecg.modules.friends.user.param.OperateAuthInfoParam;
import org.jeecg.modules.friends.utils.JacksonUtil;
import org.parboiled.common.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.IdcardUtil;


/**
 * @Description: 认证信息表
 * @Author: jeecg-boot
 * @Date: 2024-05-15
 * @Version: V1.0
 */
@Service
public class UserAuthenticationServiceImpl extends ServiceImpl<UserAuthenticationMapper, UserAuthentication>
        implements IUserAuthenticationService {
    @Autowired
    private UserAuthenticationMapper authenticationMapper;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private InvitedUserDAO invitedUserDAO;

    @Autowired
    private VipUserService vipUserService;

    @Autowired
    private SystemConfigDAO systemConfigDAO;

    @Override
    @Transactional
    public void updateUserAuthInfo(EditAuthInfoRequest request, User user) {
        LambdaQueryWrapper<UserAuthentication> query = new LambdaQueryWrapper<UserAuthentication>();
        query.eq(UserAuthentication::getUserId, user.getId());
        query.eq(UserAuthentication::getAuthType, request.getAuthType());
        authenticationMapper.delete(query);
        UserAuthentication userAuthentication = new UserAuthentication();
        userAuthentication.setUserId(user.getId());
        userAuthentication.setAuthStatus(AuthStatusEnum.SUBMITTED.getCode());
        userAuthentication.setAuthType(request.getAuthType());
        if (AuthTypeEnum.REAL_NAME.getCode() == request.getAuthType()) {
            userAuthentication.setRealName(request.getRealName());
            userAuthentication.setIdCardNo(request.getIDCardNo());
            try {
                int genderByIdCard = IdcardUtil.getGenderByIdCard(request.getIDCardNo());
                user.setGender(genderByIdCard == 1 ? "男" : "女");
                DateTime birthDate = IdcardUtil.getBirthDate(request.getIDCardNo());
                user.setBirthday(birthDate.toString("yyyy-MM-dd"));
            } catch (Exception e) {
                log.error("getGenderByIdCard error.", e);
            }
            //第三方认证接口
            if (RealNameAuthenticationUtils.authRealName(request.getRealName(), request.getIDCardNo())) {
                userAuthentication.setAuthStatus(AuthStatusEnum.SYSTEM_PASSED.getCode());
            } else {
                userAuthentication.setAuthStatus(AuthStatusEnum.SYSTEM_REJECTED.getCode());
                throw new MakeFriendsBaseException("校验未通过，请重新填写");
            }
        }
        if (AuthTypeEnum.EDUCATION_CERTIFICATION.getCode() == request.getAuthType()) {
            userAuthentication.setEducation(request.getEducation());
            userAuthentication.setUniversity(request.getUniversity());
            userAuthentication.setCertificateUrl(request.getCertificateUrl());
            userAuthentication.setAuthToken(request.getXuexinToken());

        }
        if (AuthTypeEnum.WORK_CERTIFICATION.getCode() == request.getAuthType()) {
            userAuthentication.setJob(request.getJob());
            userAuthentication.setCompanyName(request.getCompanyName());
            userAuthentication.setIsStudent(request.getIsStudent());
            userAuthentication.setCertificateUrl(request.getCertificateUrl());
        }
        userAuthentication.setAddTime(new Date());
        userAuthentication.setUpdateTime(new Date());
        authenticationMapper.insert(userAuthentication);
        user.setAuthStatus(AuthStatusEnum.SUBMITTED.getCode());
        try {
            AuthInfo authInfo = queryUserAuthInfoV2(user);
            user.setAuthStatusV2(authInfo.getAuthStatus());
        } catch (Exception e) {
            log.error("error.", e);
        }
        userMapper.updateById(user);


    }

    @Override
    public List<UserAuthentication> selectByUserId(Long userId) {
        LambdaQueryWrapper<UserAuthentication> query = new LambdaQueryWrapper<>();
        query.eq(UserAuthentication::getUserId, userId);
        return authenticationMapper.selectList(query);
    }

    @Override
    public AuthInfo queryUserAuthInfo(User user) {
        List<UserAuthentication> userAuthenticationList = selectByUserId(user.getId());
        SystemConfigDO systemConfigDO = systemConfigDAO.findOne();
        AuthInfo authInfoDTO = checkAuthInfo(userAuthenticationList, user, systemConfigDO);
        return authInfoDTO;
    }

    @Override
    public AuthInfo queryUserAuthInfoV2(User user) {
        List<UserAuthentication> userAuthenticationList = selectByUserId(user.getId());
        SystemConfigDO systemConfigDO = systemConfigDAO.findOne();
        AuthInfo authInfoDTO = checkAuthInfoBackV2(userAuthenticationList, user, systemConfigDO);
        return authInfoDTO;
    }

    public static AuthInfo checkAuthInfo(List<UserAuthentication> userAuthenticationList, User user,
            SystemConfigDO systemConfigDO) {
        AuthInfo authInfoDTO = new AuthInfo();
        List<UserAuthentication> userAuthentications = userAuthenticationList.stream()
                .filter((x) -> x.getAuthType().equals(AuthTypeEnum.EDUCATION_CERTIFICATION.getCode()))
                .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(userAuthentications)) {
            UserAuthentication userAuthentication = userAuthentications.get(0);
            EducationTypeEnum educationTypeEnum = EducationTypeEnum.getEnumByName(userAuthentication.getEducation());
            if (educationTypeEnum != null) {
                authInfoDTO.setEducationType(educationTypeEnum.getCode());
            }
        }
        if (StringUtils.isNotEmpty(user.getExtData())) {
            UserExtDTO userExtDTO = JacksonUtil.readValue(user.getExtData(), UserExtDTO.class);
            if (Objects.nonNull(userExtDTO)) {
                authInfoDTO.setIsFirstCommit(userExtDTO.getIsFirstCommit());
                authInfoDTO.setAuthStatus(userExtDTO.getAuthStatus());
                authInfoDTO.setShowInvitedUrl(userExtDTO.getShowInviteUrl());
                if (authInfoDTO.getShowInvitedUrl() != null && authInfoDTO.getShowInvitedUrl() && Objects
                        .nonNull(systemConfigDO)) {
                    authInfoDTO.setInvitedUrl(systemConfigDO.getInvitedUrl());
                }
            }
        }
        if (CollectionUtils.isEmpty(userAuthenticationList)) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.INITIALIZE.getCode());
            return authInfoDTO;
        }
        List<UserAuthentication> unPassed =
                userAuthenticationList.stream()
                        .filter(auth -> (auth.getAuthStatus().equals(AuthStatusEnum.UN_PASSED.getCode())))
                        .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(unPassed)) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.UN_PASSED.getCode());
            return authInfoDTO;
        }

        List<UserAuthentication> passedRecord = userAuthenticationList.stream()
                .filter(auth -> (auth.getAuthStatus().equals(AuthStatusEnum.PASSED.getCode())))
                .collect(Collectors.toList());

        // 3个都认证通过，即为通过
        if (CollectionUtils.isNotEmpty(passedRecord) && passedRecord.size() >= 3) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.PASSED.getCode());
            return authInfoDTO;
        }

        // 信息都提交了，
        List<UserAuthentication> submitted =
                userAuthenticationList.stream().filter(auth -> auditStatus().contains(auth.getAuthStatus()))
                        .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(submitted) && submitted.size() == 3) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.SUBMITTED.getCode());
            return authInfoDTO;
        }

        // 信息都提交了，
        List<UserAuthentication> auditing =
                userAuthenticationList.stream().filter(auth -> auditIng().contains(auth.getAuthStatus()))
                        .collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(auditing)) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.SUBMITTED.getCode());
            return authInfoDTO;
        }
        authInfoDTO.setAuthStatus(AuthStatusEnum.INITIALIZE.getCode());
        return authInfoDTO;
    }

    public static AuthInfo checkAuthInfoBackV2(List<UserAuthentication> userAuthenticationList, User user,
            SystemConfigDO systemConfigDO) {
        AuthInfo authInfoDTO = new AuthInfo();
        if (StringUtils.isNotEmpty(user.getExtData())) {
            UserExtDTO userExtDTO = JacksonUtil.readValue(user.getExtData(), UserExtDTO.class);
            if (Objects.nonNull(userExtDTO)) {
                authInfoDTO.setIsFirstCommit(userExtDTO.getIsFirstCommit());
                authInfoDTO.setAuthStatus(userExtDTO.getAuthStatus());
                authInfoDTO.setShowInvitedUrl(userExtDTO.getShowInviteUrl());
                if (authInfoDTO.getShowInvitedUrl() != null && authInfoDTO.getShowInvitedUrl() && Objects
                        .nonNull(systemConfigDO)) {
                    authInfoDTO.setInvitedUrl(systemConfigDO.getInvitedUrl());
                }
            }
        }
        if (CollectionUtils.isEmpty(userAuthenticationList)) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.INITIALIZE.getCode());
            return authInfoDTO;
        }
        List<UserAuthentication> unPassed =
                userAuthenticationList.stream()
                        .filter(auth -> (auth.getAuthStatus().equals(AuthStatusEnum.UN_PASSED.getCode())))
                        .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(unPassed)) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.UN_PASSED.getCode());
            return authInfoDTO;
        }

        List<UserAuthentication> passedRecord = userAuthenticationList.stream()
                .filter(auth -> (auth.getAuthStatus().equals(AuthStatusEnum.PASSED.getCode())))
                .collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(passedRecord) && passedRecord.size() == userAuthenticationList.size()
                && userAuthenticationList.size() >= 3) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.PASSED.getCode());
            return authInfoDTO;
        }

        List<UserAuthentication> submitted =
                userAuthenticationList.stream().filter(auth -> auditStatusV2().contains(auth.getAuthStatus()))
                        .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(submitted) && submitted.size() == 3) {
            authInfoDTO.setAuthStatus(AuthStatusEnum.SUBMITTED.getCode());
            return authInfoDTO;
        }
        authInfoDTO.setAuthStatus(AuthStatusEnum.INITIALIZE.getCode());
        return authInfoDTO;
    }

    @Override
    public AuthDetailInfo queryAuthDetailInfo(User user) {
        List<UserAuthentication> userAuthentications = selectByUserId(user.getId());
        AuthDetailInfo authDetailInfo = new AuthDetailInfo();
        for (UserAuthentication userAuthentication : userAuthentications) {
            if (userAuthentication.getAuthType() == AuthTypeEnum.REAL_NAME.getCode()) {
                IDCardAuthInfo authInfo = new IDCardAuthInfo();
                authInfo.setAuthId(userAuthentication.getId());

                try {
                    if (StringUtils.isNotEmpty(userAuthentication.getRealName())) {
                        authInfo.setRealName(userAuthentication.getRealName().substring(0, 1) + "**");
                    }
                    if (StringUtils.isNotEmpty(userAuthentication.getIdCardNo())) {
                        authInfo.setIdCardNo(userAuthentication.getIdCardNo().substring(0, 3) + "****");
                    }
                } catch (Exception e) {
                    authInfo.setIdCardNo(userAuthentication.getIdCardNo());
                }
                authInfo.setAuthTime(userAuthentication.getUpdateTime().getTime());
                authInfo.setUnpassReason(userAuthentication.getRemark());
                if (auditStatus().contains(userAuthentication.getAuthStatus())) {
                    authInfo.setAuthStatusCode(AuthStatusEnum.SUBMITTED.getCode());
                    authInfo.setAuthStatus(AuthStatusEnum.SUBMITTED.getDesc());
                } else {
                    authInfo.setAuthStatusCode(userAuthentication.getAuthStatus());
                    authInfo.setAuthStatus(AuthStatusEnum.of(userAuthentication.getAuthStatus()).getDesc());
                }
                authDetailInfo.setIdCardAuthInfo(authInfo);
            }
            if (userAuthentication.getAuthType() == AuthTypeEnum.EDUCATION_CERTIFICATION.getCode()) {
                EducationAuthInfo educationAuthInfo = new EducationAuthInfo();
                educationAuthInfo.setAuthId(userAuthentication.getId());
                educationAuthInfo.setAuthTime(userAuthentication.getUpdateTime().getTime());
                if (auditStatus().contains(userAuthentication.getAuthStatus())) {
                    educationAuthInfo.setAuthStatusCode(AuthStatusEnum.SUBMITTED.getCode());
                    educationAuthInfo.setAuthStatus(AuthStatusEnum.SUBMITTED.getDesc());
                } else {
                    educationAuthInfo.setAuthStatusCode(userAuthentication.getAuthStatus());
                    educationAuthInfo.setAuthStatus(AuthStatusEnum.of(userAuthentication.getAuthStatus()).getDesc());
                }
                educationAuthInfo.setUnpassReason(userAuthentication.getRemark());
                educationAuthInfo.setEducation(userAuthentication.getEducation());
                educationAuthInfo.setUniversity(userAuthentication.getUniversity());
                educationAuthInfo.setCertificateUrl(userAuthentication.getCertificateUrl());
                authDetailInfo.setEducationAuthInfo(educationAuthInfo);
            }

            if (userAuthentication.getAuthType() == AuthTypeEnum.WORK_CERTIFICATION.getCode()) {
                JobAuthInfo jobAuthInfo = new JobAuthInfo();
                jobAuthInfo.setAuthId(userAuthentication.getId());
                jobAuthInfo.setUnpassReason(userAuthentication.getRemark());
                jobAuthInfo.setJob(userAuthentication.getJob());
                jobAuthInfo.setCompanyName(userAuthentication.getCompanyName());
                jobAuthInfo.setCertificateUrl(userAuthentication.getCertificateUrl());
                jobAuthInfo.setAuthTime(userAuthentication.getUpdateTime().getTime());
                if (auditStatus().contains(userAuthentication.getAuthStatus())) {
                    jobAuthInfo.setAuthStatusCode(AuthStatusEnum.SUBMITTED.getCode());
                    jobAuthInfo.setAuthStatus(AuthStatusEnum.SUBMITTED.getDesc());
                } else {
                    jobAuthInfo.setAuthStatusCode(userAuthentication.getAuthStatus());
                    jobAuthInfo.setAuthStatus(AuthStatusEnum.of(userAuthentication.getAuthStatus()).getDesc());
                }
                jobAuthInfo.setIsStudent(userAuthentication.getIsStudent());
                authDetailInfo.setJobAuthInfo(jobAuthInfo);
            }
        }
        return authDetailInfo;
    }

    @Override
    public void operateAuthInfo(OperateAuthInfoParam param) {
        SystemConfigDO systemConfigDO = systemConfigDAO.findOne();
        UserAuthentication userAuthentication = authenticationMapper.selectById(param.getAuthId());
        if (Objects.isNull(userAuthentication)) {
            throw new MakeFriendsBaseException("认证信息不存在，入参有误");
        }
        User user = userMapper.selectById(userAuthentication.getUserId());
        userAuthentication.setRemark(param.getRemark());

        if (param.getOperateType() == 1) {
            userAuthentication.setAuthStatus(AuthStatusEnum.PASSED.getCode());
            authenticationMapper.updateById(userAuthentication);
            AuthInfo authInfo = queryUserAuthInfo(user);
            if (authInfo.getAuthStatus() == AuthStatusEnum.PASSED.getCode()) {

                UserExtDTO userExtDTO = null;
                if (StringUtils.isNotEmpty(user.getExtData())) {
                    userExtDTO = JacksonUtil.readValue(user.getExtData(), UserExtDTO.class);
                }
                if (Objects.isNull(userExtDTO)) {
                    userExtDTO = new UserExtDTO();
                }
                InvitedUserDO invitedUserDO = invitedUserDAO.queryByInvitedUserId(user.getId());
                if (Objects.nonNull(invitedUserDO)) {
                    User fromUser = userMapper.selectById(invitedUserDO.getUserId());
                    if (fromUser != null) {
                        if (systemConfigDO != null && systemConfigDO.getInviteUserVip() != null) {
                            vipUserService.addVipUser(fromUser, 1, systemConfigDO.getInviteUserVip(),
                                    systemConfigDO.getInviteUserVip() * 24 * 3600L * 1000);
                            invitedUserDO.setInviteDayCount(systemConfigDO.getInviteUserVip());
                        } else {
                            vipUserService.addVipUser(fromUser, 1, 7, 3 * 24 * 3600L * 1000);
                            invitedUserDO.setInviteDayCount(3);
                        }
                        invitedUserDAO.update(invitedUserDO);
                    }
                }
                userExtDTO.setAuthStatus(AuthStatusEnum.PASSED.getCode());
                userExtDTO.setIsFirstCommit(true);
                userExtDTO.setShowInviteUrl(true);
                user.setExtData(JacksonUtil.writeValueAsString(userExtDTO));
                user.setAuthStatus(AuthStatusEnum.PASSED.getCode());
                user.setAuthStatusV2(AuthStatusEnum.PASSED.getCode());
                user.setRecommended(true);
                user.setEducationType(authInfo.getEducationType());
                userMapper.updateById(user);
            }
        }
        if (param.getOperateType() == 2) {
            userAuthentication.setAuthStatus(AuthStatusEnum.UN_PASSED.getCode());
            //TODO 发短信
            user.setAuthStatus(AuthStatusEnum.UN_PASSED.getCode());
            user.setAuthStatusV2(AuthStatusEnum.UN_PASSED.getCode());
            userMapper.updateById(user);
            authenticationMapper.updateById(userAuthentication);
        }
    }

    @Override
    public List<UserAuthentication> selectByUserIdSet(Set<Long> userIdSet) {
        LambdaQueryWrapper<UserAuthentication> userAuthenticationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userAuthenticationLambdaQueryWrapper.in(UserAuthentication::getUserId, userIdSet);
        return authenticationMapper.selectList(userAuthenticationLambdaQueryWrapper);
    }

    @Override
    public void deleteByUserId(Long userId) {
        LambdaQueryWrapper<UserAuthentication> userAuthenticationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userAuthenticationLambdaQueryWrapper.eq(UserAuthentication::getUserId, userId);
        authenticationMapper.delete(userAuthenticationLambdaQueryWrapper);
    }

    private static List<Integer> auditStatus() {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(AuthStatusEnum.SUBMITTED.getCode());
        statusList.add(AuthStatusEnum.SYSTEM_PASSED.getCode());
        statusList.add(AuthStatusEnum.SYSTEM_REJECTED.getCode());
        return statusList;
    }

    private static List<Integer> auditIng() {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(AuthStatusEnum.SUBMITTED.getCode());
        return statusList;
    }

    private static List<Integer> auditStatusV2() {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(AuthStatusEnum.SUBMITTED.getCode());
        statusList.add(AuthStatusEnum.SYSTEM_PASSED.getCode());
        statusList.add(AuthStatusEnum.SYSTEM_REJECTED.getCode());
        statusList.add(AuthStatusEnum.PASSED.getCode());
        return statusList;
    }
}
